package com.wiscamp.ninechapters.panels.domain.services;

import com.wiscamp.ninechapters.panels.domain.repositories.PanelsErrorCodes;
import com.wiscamp.ninechapters.panels.domain.entities.Menu;
import com.wiscamp.ninechapters.panels.domain.repositories.MenuRepository;
import cube.common.cache.CacheManagerNames;
import cube.ddd.aspect.HandleServiceException;
import cube.ddd.domain.DomainService;
import cube.ddd.exception.ExceptionUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.Objects;

@Service
public class MenuService implements DomainService {
    private final MenuRepository menuRepository;

    private final String cacheName = "menus";

    public MenuService(MenuRepository menuRepository) {
        this.menuRepository = menuRepository;
    }

    @HandleServiceException
    @Cacheable(value = cacheName, key = "#menuId", cacheManager = CacheManagerNames.SIXTY_MINUTES_CACHE)
    public Menu getMenu(long menuId) {
        var menu = menuRepository.getMenu(menuId);
        if (Objects.isNull(menu)) {
            ExceptionUtils.throwServiceException(PanelsErrorCodes.MENU_NOT_FOUND, menuId);
        }
        return menu;
    }

    @HandleServiceException
    @CachePut(value = cacheName, key = "#menu.menuId", cacheManager = CacheManagerNames.SIXTY_MINUTES_CACHE)
    public Menu createMenu(Menu menu, long operatorId) {
        var existedMenu = menuRepository.getMenuByCode(menu.getApplicationId(), menu.getMenuCode());
        if (Objects.nonNull(existedMenu)) {
            ExceptionUtils.throwServiceException(PanelsErrorCodes.MENU_CODE_EXISTED, menu);
        }

        menu.createBy(operatorId);
        return menuRepository.saveMenu(menu);
    }

    @HandleServiceException
    @CachePut(value = cacheName, key = "#menu.menuId", cacheManager = CacheManagerNames.SIXTY_MINUTES_CACHE)
    public Menu updateMenu(Menu menu, long operatorId) {
        var existedMenu = getMenu(menu.getMenuId());

        existedMenu = menuRepository.getMenuByCode(menu.getApplicationId(), menu.getMenuCode());
        if (Objects.nonNull(existedMenu) && existedMenu.getMenuId() != menu.getMenuId()) {
            ExceptionUtils.throwServiceException(PanelsErrorCodes.MENU_CODE_EXISTED, menu);
        }
        menu.updateBy(operatorId);
        return menuRepository.saveMenu(menu);
    }

    @HandleServiceException
    @CacheEvict(value = cacheName, key = "#menuId")
    public boolean enableMenu(long menuId, long operatorId) {
        var menu = getMenu(menuId);
        if (Objects.isNull(menu)) return false;
        // 记录操作日志
        menu.enable();
        menu.updateBy(operatorId);
        menuRepository.saveMenu(menu);
        return true;
    }

    @HandleServiceException
    @CacheEvict(value = cacheName, key = "#menuId")
    public boolean disableMenu(long menuId, long operatorId) {
        var menu = getMenu(menuId);
        if (Objects.isNull(menu)) return false;
        // 记录操作日志
        menu.disable();
        menu.updateBy(operatorId);
        menuRepository.saveMenu(menu);
        return true;
    }

    @HandleServiceException
    @CacheEvict(value = cacheName, key = "#menuId")
    public boolean deleteMenu(long menuId, long operatorId) {
        var menu = getMenu(menuId);
        if (Objects.isNull(menu)) return false;
        // 记录操作日志
        menu.delete();
        menu.updateBy(operatorId);
        menuRepository.saveMenu(menu);
        return true;
    }
}
